package com.lswms.service.impl;

import cn.hutool.core.util.StrUtil;
import com.lswms.common.constant.Constant;
import com.lswms.common.exception.ErrorCode;
import com.lswms.common.exception.RenException;
import com.lswms.common.page.PageInfo;
import com.lswms.common.page.PageRequest;
import com.lswms.common.redis.RedisUtils;
import com.lswms.common.service.impl.CrudServiceImpl;
import com.lswms.common.utils.HttpClientUtils;
import com.lswms.common.utils.MoneyUtil;
import com.lswms.common.utils.ZqDateUtil;
import com.lswms.dao.YnPayRecordDao;
import com.lswms.dto.YnPayRecordDTO;
import com.lswms.dto.vo.req.CashOutReq;
import com.lswms.dto.vo.req.ChargeReq;
import com.lswms.dto.vo.req.QueryAmountReq;
import com.lswms.dto.vo.resp.QueryAmountResp;
import com.lswms.dto.vo.resp.TradeListResp;
import com.lswms.entity.YnBankcardEntity;
import com.lswms.entity.YnLotteryTicketActivityEntity;
import com.lswms.entity.YnPayRecordEntity;
import com.lswms.entity.YnSignEntity;
import com.lswms.entity.YnUserEntity;
import com.lswms.service.YnBankcardService;
import com.lswms.service.YnLotteryTicketActivityService;
import com.lswms.service.YnPayRecordService;
import com.lswms.service.YnUserService;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import lombok.extern.slf4j.Slf4j;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;

/**
 * 支付记录表
 *
 * @author Mark sunlightcs@gmail.com
 * @since 1.0.0 2020-04-25
 */
@Service
@Slf4j
public class YnPayRecordServiceImpl extends CrudServiceImpl<YnPayRecordDao, YnPayRecordEntity, YnPayRecordDTO> implements YnPayRecordService {

	@Autowired
	private YnUserService ynUserService;
	
	@Autowired
	private YnBankcardService ynBankcardService;
	
	@Autowired
	private YnLotteryTicketActivityService ynLotteryTicketActivityService;
	
    @Autowired
    private RedisUtils redisUtils;

	
    @Override
    public QueryWrapper<YnPayRecordEntity> getWrapper(Map<String, Object> params){
    	Long id = (Long)params.get("id");
    	String businessType = (String)params.get("businessType");
    	Integer status = (Integer)params.get("status");
    	String d1 = (String)params.get("d1");
    	String d2 = (String)params.get("d2");
    	String uuid = (String)params.get("uuid");

        QueryWrapper<YnPayRecordEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(id != null, "id", id);
        wrapper.eq(StringUtils.isNotBlank(businessType), "business_type", businessType);
        wrapper.eq(status != null, "status", status);
        wrapper.eq(StringUtils.isNotBlank(uuid), "uuid", uuid);
        wrapper.between("create_date",d1 , d2);

        return wrapper;
    }

    /**
     * 充值
     */
	@Override
	public String charge(ChargeReq dto, YnUserEntity ynuser) {
		log.info("充值，参数dto:{},ynuser:{}",JSON.toJSONString(dto),JSON.toJSONString(ynuser));
		//判断金额
		BigDecimal amount = MoneyUtil.convertBigDecimal(dto.getAmount());
		if(amount.compareTo(BigDecimal.ZERO) <= 0){
			throw new RenException(ErrorCode.AMOUNT_ERROR);
		}
		//0：充值，1：信用升级
		String type = dto.getType();
		String bus = "";
		String remark = "";
		if("0".equals(type)){
			bus = "CHARGE";
			remark = "充值";
		}else if("1".equals(type)){
			bus = "UPCREDIT";
			remark = "信用升级";
		}
		//添加交易记录
		String uuid = payrecord(ynuser.getId(),null,bus,"bank",amount,remark);
		return uuid;
	}

	/**
	 * 添加交易记录
	 * @param userId
	 * @param bankId
	 * @param businessType
	 * @param type
	 * @param amt
	 * @param remark
	 */
	public String payrecord(Long userId,Long bussId,String businessType,String type,BigDecimal amt,String remark){
		YnPayRecordEntity pay = new YnPayRecordEntity();
		pay.setUserId(userId);
		pay.setBusinessType(businessType);
		pay.setType(type);
		pay.setUuid(UUID.randomUUID().toString().replaceAll("-", ""));
		pay.setBusinessId(bussId);
		pay.setChannel("app");
		pay.setAmt(amt);
		pay.setStatus(0);
		pay.setRemark(remark);
		pay.setYearmonth(ZqDateUtil.yyyy_MM());
		pay.setCreateDate(ZqDateUtil.getNow());
		pay.setCreator(userId);
		pay.setUpdateDate(ZqDateUtil.getNow());
		
		baseDao.insert(pay);
		return pay.getUuid();
	}
	/**
	 * 充值回调
	 * CHARGE:充值
	 */
	@Override
	@Transactional
	public String notify(String type,String tradNo, HttpServletRequest request) {
		log.info("开始充值回调参数:type:{},tradNo:{}",type,tradNo);
		if(StringUtils.isBlank(tradNo)){
			throw new RenException(ErrorCode.TRAD_ERROR);
		}
		//查询交易是否存在
		QueryWrapper<YnPayRecordEntity> wrapper = new QueryWrapper<YnPayRecordEntity>();
		wrapper.eq(StringUtils.isNotBlank(tradNo), "uuid", tradNo);
		wrapper.eq("status", 0);
		YnPayRecordEntity record = baseDao.selectOne(wrapper);
		log.info("充值回调参数:record:{}",JSON.toJSONString(record));
		if(record == null){
			throw new RenException(ErrorCode.TRAD_ERROR);
		}
		//更新用户余额
		BigDecimal totalBalance = BigDecimal.ZERO;
		//充值+余额
        JSONObject retJson = HttpClientUtils.httpGet("http://149.129.235.68:29918/pay/api/in/getPayStatus?appKey=54fff46929fb49de8ed298e2026ec444&transactionId="+tradNo);
        log.info("查询支付状态结果：{}",JSON.toJSONString(retJson));
        
        if(retJson != null && retJson.getIntValue("code") == 200 
        		&& "SUCCESS".equals(retJson.getString("message"))) {
        	
        	JSONObject retJson1 = (JSONObject)retJson.get("result");
        	if(retJson1 != null){
            	String uuid = retJson1.getString("transactionId");
            	String payStatus = retJson1.getString("payStatus");
            	int payMoney = retJson1.getIntValue("payMoney");
            	if("SUCCESS".equals(payStatus) && uuid.equals(tradNo) 
            			&& record.getAmt().compareTo(new BigDecimal(payMoney)) == 0){
            		
            		//充值加余额
            		if("CHARGE".equals(record.getBusinessType())){
                		//更新用户余额、更新交易状态
            			YnUserEntity ynuser = ynUserService.selectById(record.getUserId());
            			
            			totalBalance = ynuser.getBalance().add(record.getAmt());
            			YnUserEntity user = new YnUserEntity();
            			user.setId(ynuser.getId());
            			user.setBalance(totalBalance);
            			user.setUpdateDate(ZqDateUtil.getNow());
            			ynUserService.updateById(user);
            			
            			try{
                			//充值送彩金，充多少送多少
                			chargeSendReward(ynuser,record.getAmt(),tradNo);
            			}catch(Exception e){
            				log.info("活动，异常：{}",e);
            			}
            		}
        			//修改交易状态
        			Long payid = record.getId();
        			record = new YnPayRecordEntity();
        			record.setId(payid);
        			record.setStatus(1);
        			record.setUpdateDate(ZqDateUtil.getNow());
        			baseDao.updateById(record);

            	}
        	}
        }
		log.info("结束充值回调操作。。。。。。。");
		return "success";
	}
	//充值送彩金，充多少送多少
	public void chargeSendReward(YnUserEntity ynuser,BigDecimal reward,String transId){
		//添加领取奖励记录
		YnLotteryTicketActivityEntity entity = new YnLotteryTicketActivityEntity();
		entity.setActivityCode("CHARGE_SEND_REWARD");
		entity.setAmount(reward);
		entity.setUserId(ynuser.getId());
		entity.setTitle("充值送奖励");
		entity.setContent(transId);
		entity.setCreateDate(ZqDateUtil.getNow());
		ynLotteryTicketActivityService.insert(entity);
		//更新用户奖励余额
		BigDecimal totalBalance = ynuser.getReward().add(reward);
		YnUserEntity user = new YnUserEntity();
		user.setId(ynuser.getId());
		user.setReward(totalBalance);
		user.setUpdateDate(ZqDateUtil.getNow());
		ynUserService.updateById(user);

	}

	/**
	 * 提现
	 */
	@Override
	public String cashOut(CashOutReq dto, YnUserEntity ynuser) {
		log.info("提现，参数dto:{},ynuser:{}",JSON.toJSONString(dto),JSON.toJSONString(ynuser));
		//判断金额
		BigDecimal amount = MoneyUtil.convertBigDecimal(dto.getAmount());
		if(amount.compareTo(BigDecimal.ZERO) <= 0){
			throw new RenException(ErrorCode.AMOUNT_ERROR);
		}
		//判断银行卡提现信息
		/*YnBankcardEntity bankcard = ynBankcardService.selectById(Long.parseLong(dto.getBankId()));
		if(bankcard == null){
			throw new RenException(ErrorCode.BANK_ERROR);
		}
		if(!bankcard.getUserId().equals(ynuser.getId())){
			throw new RenException(ErrorCode.BANK_ERROR);
		}*/
		//判断金额
		if(amount.compareTo(new BigDecimal(50000)) < 0){
			throw new RenException(ErrorCode.AMOUNT_LESS);
		}
		if(ynuser.getBalance().compareTo(amount) < 0){
			throw new RenException(ErrorCode.AMOUNT_ERROR);
		}
		//提现减去余额
		BigDecimal totalBalance = ynuser.getBalance().subtract(amount);
		YnUserEntity user = new YnUserEntity();
		user.setId(ynuser.getId());
		user.setBalance(totalBalance);
		user.setUpdateDate(ZqDateUtil.getNow());
		ynUserService.updateById(user);

		//添加交易记录
		return payrecord(ynuser.getId(),null,"CASHOUT","bank",amount,"提现");
	}
	/**
	 * 查询收入支出
	 */
	@Override
	public QueryAmountResp queryAmount(QueryAmountReq dto, YnUserEntity ynuser) {
		log.info("查询收入支出，参数dto:{},ynuser:{}",JSON.toJSONString(dto),JSON.toJSONString(ynuser));
		//查询交易是否存在
		QueryWrapper<YnPayRecordEntity> wrapper = new QueryWrapper<YnPayRecordEntity>();
		wrapper.eq(StringUtils.isNotBlank(dto.getYearMonth()), "yearmonth", dto.getYearMonth());
		List<YnPayRecordEntity> list = baseDao.selectList(wrapper);
		//收入
		BigDecimal income = BigDecimal.ZERO;
		//支出
		BigDecimal pay = BigDecimal.ZERO;
		//CHARGE:充值，CASHOUT:提现，SIGNOUT：打卡金额，SIGN:打卡瓜分，BACK:退还，LOTTERY:抽奖，LOTTERY_TICKET:购买彩票，LOTTERY_TICKET_REWARD:彩票中奖
		for(YnPayRecordEntity payRec :list){
			if("CHARGE".equals(payRec.getBusinessType()) || "LOTTERY_TICKET_REWARD".equals(payRec.getBusinessType())){
				income = income.add(payRec.getAmt());
			}else if("CASHOUT".equals(payRec.getBusinessType()) || "LOTTERY_TICKET".equals(payRec.getBusinessType())){
				pay = pay.add(payRec.getAmt());
			}
		}
		QueryAmountResp resp = new QueryAmountResp();
		resp.setIncome(MoneyUtil.bigDecimal2String(income, 2));
		resp.setPay(MoneyUtil.bigDecimal2String(pay,2));
		log.info("查询收入支出返回:{}",JSON.toJSONString(resp));
		return resp;
	}

	/**
	 * 交易记录
	 */
	@Override
	public PageInfo<TradeListResp> tradeList(PageRequest dto,
			YnUserEntity ynuser) {
		log.info("交易记录，参数dto:{},ynuser:{}",JSON.toJSONString(dto),JSON.toJSONString(ynuser));
        QueryWrapper<YnPayRecordEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", ynuser.getId());
        wrapper.ne("business_type", "BACK");
        
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("page", dto.getPageNo());
        params.put("limit", dto.getPageSize());

		IPage<YnPayRecordEntity> pageInfo = baseDao.selectPage(getPage(params, "create_date", false),wrapper);
		
		List<TradeListResp> list = new ArrayList<TradeListResp>();
		for(YnPayRecordEntity entity : pageInfo.getRecords()){
			TradeListResp resp = new TradeListResp();
			//CHARGE:充值，CASHOUT:提现，SIGN:打卡，BACK:退还，LOTTERY:抽奖
			if("CHARGE".equals(entity.getBusinessType())){
				resp.setTitle("Isi ulang");
				resp.setType("1");
				resp.setAmount("+"+MoneyUtil.bigDecimal2String(entity.getAmt(), 2));
			}else if("CASHOUT".equals(entity.getBusinessType())){
				resp.setTitle("menarik");
				resp.setType("2");
				resp.setAmount("-"+MoneyUtil.bigDecimal2String(entity.getAmt(), 2));
			}else if("SIGN".equals(entity.getBusinessType())){
				resp.setTitle("瓜分金额");
				resp.setType("3");
				resp.setAmount("+"+MoneyUtil.bigDecimal2String(entity.getAmt(), 2));
			}else if("LOTTERY".equals(entity.getBusinessType())){
				resp.setTitle("抽奖奖金");
				resp.setType("4");
				resp.setAmount("+"+MoneyUtil.bigDecimal2String(entity.getAmt(), 2));
			}else if("SIGNOUT".equals(entity.getBusinessType())){
				resp.setTitle("打卡");
				resp.setType("5");
				resp.setAmount("-"+MoneyUtil.bigDecimal2String(entity.getAmt(), 2));
			}else if("LOTTERY_TICKET".equals(entity.getBusinessType())){
				resp.setTitle("membeli");
				resp.setType("6");
				resp.setAmount("-"+MoneyUtil.bigDecimal2String(entity.getAmt(), 2));
			}else if("LOTTERY_TICKET_REWARD".equals(entity.getBusinessType())){
				resp.setTitle("Kemenangan");
				resp.setType("7");
				resp.setAmount("+"+MoneyUtil.bigDecimal2String(entity.getAmt(), 2));
			}
			resp.setTime(ZqDateUtil.yyyyMMddHHmmss(entity.getCreateDate()));
			list.add(resp);
		}
		
		PageInfo<TradeListResp> pageList = new PageInfo<TradeListResp>();
		pageList.setCount(pageInfo.getTotal());
		pageList.setList(list);
		pageList.setPageNo(Long.parseLong(dto.getPageNo()));
		pageList.setPages(pageInfo.getPages());
		pageList.setPageSize(Long.parseLong(dto.getPageSize()));
		log.info("交易记录，结果:{}",JSON.toJSONString(pageList));
		return pageList;
	}

	/**
	 * 提现回调
	 */
	@Override
	public String notifyCashOut(String type, String tradNo,
			HttpServletRequest request) {
		log.info("开始提现回调参数:type:{},tradNo:{}",type,tradNo);
		if(StringUtils.isBlank(tradNo)){
			throw new RenException(ErrorCode.TRAD_ERROR);
		}
		//查询交易是否存在
		QueryWrapper<YnPayRecordEntity> wrapper = new QueryWrapper<YnPayRecordEntity>();
		wrapper.eq(StringUtils.isNotBlank(tradNo), "uuid", tradNo);
		wrapper.eq("status", 0);
		YnPayRecordEntity record = baseDao.selectOne(wrapper);
		if(record == null){
			throw new RenException(ErrorCode.TRAD_ERROR);
		}
		log.info("提现回调参数:record:{}",JSON.toJSONString(record));
		//提现-余额
		if("CASHOUT".equals(type)){
            JSONObject retJson = HttpClientUtils.httpGet("http://149.129.235.68:29918/pay/api/out/getPayStatus?appKey=54fff46929fb49de8ed298e2026ec444&transactionId="+tradNo);
            log.info("查询支付状态结果：{}",JSON.toJSONString(retJson));
            
            if(retJson != null && retJson.getIntValue("code") == 200 
            		&& "SUCCESS".equals(retJson.getString("message"))) {
            	
            	JSONObject retJson1 = (JSONObject)retJson.get("result");
            	if(retJson1 != null){
                	String uuid = retJson1.getString("transactionId");
                	String payStatus = retJson1.getString("payStatus");
                	int payMoney = retJson1.getIntValue("payMoney");
                	if("SUCCESS".equals(payStatus) && uuid.equals(tradNo) 
                			&& record.getAmt().compareTo(new BigDecimal(payMoney)) == 0){
            			//修改交易状态
                		Long payid = record.getId();
            			record = new YnPayRecordEntity();
            			record.setId(payid);
            			record.setStatus(1);
            			record.setUpdateDate(ZqDateUtil.getNow());
            			baseDao.updateById(record);

                	}
            	}
            }
		}
		log.info("结束提现回调操作。。。。。。。");
		return "success";	}


	@Override
	public PageInfo<YnPayRecordDTO> listByCondition(PageRequest dto, String startTime, String endTime) {
		Map<String,Object> pageParam = new HashMap<>();
		pageParam.put(Constant.PAGE,dto.getPageNo());
		pageParam.put(Constant.LIMIT, dto.getPageSize());
		IPage pageList =  baseDao.selectPage(
				getPage(pageParam,"create_date",false),
				new QueryWrapper<YnPayRecordEntity>()
						.le(StrUtil.isNotEmpty(endTime), "create_date", endTime)
						.ge(StrUtil.isNotEmpty(startTime), "create_date", startTime)
		);
		PageInfo<YnPayRecordDTO> pageInfo = new PageInfo<YnPayRecordDTO>();
		pageInfo.setCount(pageList.getTotal());
		pageInfo.setList(pageList.getRecords());
		pageInfo.setPages(pageList.getPages());
		pageInfo.setPageNo(Long.parseLong(dto.getPageNo()));
		pageInfo.setPageSize(Long.parseLong(dto.getPageSize()));
		return pageInfo;
	}

	/**
	 * 每日数据
	 */
	@Override
	public String cdata(String s, String e) {
        QueryWrapper<YnPayRecordEntity> wrapper = new QueryWrapper<>();
		wrapper.ge("create_date", s);
		wrapper.le("create_date", e);
		wrapper.eq("business_type", "CHARGE");
		List<YnPayRecordEntity> order = baseDao.selectList(wrapper);
		int size = order.size();
		
		wrapper.groupBy("user_id");
		List<YnPayRecordEntity> order1 = baseDao.selectList(wrapper);
		int size1 = order1.size();
		
        QueryWrapper<YnPayRecordEntity> wrapper1 = new QueryWrapper<>();
		wrapper1.ge("create_date", s);
		wrapper1.le("create_date", e);
		wrapper1.eq("business_type", "CHARGE");
		wrapper1.eq("status", 1);
		List<YnPayRecordEntity> order2 = baseDao.selectList(wrapper1);
		int size2 = order2.size();

		return size+","+size1+","+size2;

	}
}